package ui.swing.textcomponent;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.Element;
import javax.swing.undo.UndoableEdit;

public class TextArea_Element extends JFrame implements UndoableEditListener,
		DocumentListener {

	private UndoableEdit undoEdit;
	private JTextArea jta;
	private JTextArea message;
	private JMenuItem undoItem;
	private JMenuItem redoItem;

	public TextArea_Element() {
		super("TextArea Demo");
		setBounds(100, 100, 680, 540);

		jta = new JTextArea();
		jta.getDocument().addUndoableEditListener(this);
		jta.getDocument().addDocumentListener(this);

		message = new JTextArea();
		message.setEditable(false); // message不可编辑

		JPanel p1 = new JPanel();
		p1.setLayout(new GridLayout(1, 1));
		p1.setBorder(BorderFactory.createTitledBorder("Edit Area"));
		p1.add(new JScrollPane(jta));

		JPanel p2 = new JPanel();
		p2.setLayout(new GridLayout(1, 1));
		p2.setBorder(BorderFactory.createTitledBorder("Message"));
		p2.add(new JScrollPane(message));

		getContentPane().setLayout(new GridLayout(2, 1));
		getContentPane().add(p1);
		getContentPane().add(p2);

		JMenuBar bar = new JMenuBar();
		JMenu theMenu = new JMenu("Edit");
		undoItem = new JMenuItem("Undo");
		redoItem = new JMenuItem("Redo");
		theMenu.add(undoItem);
		theMenu.add(redoItem);
		bar.add(theMenu);
		setJMenuBar(bar);

		updateMenuItem(); // 构造目录菜单

		undoItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ev) {
				undoEdit.undo();
				updateMenuItem();// 运行undo功能
				message.append("- Undo -\n");
			}
		});

		redoItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ev) {
				undoEdit.redo();
				updateMenuItem();// 运行redo功能
				message.append("- Redo -\n");
			}
		});

		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
	}

	public void updateMenuItem() {
		if (undoEdit != null) {
			undoItem.setEnabled(undoEdit.canUndo());
			redoItem.setEnabled(undoEdit.canRedo());
			undoItem.setText(undoEdit.getUndoPresentationName());
			redoItem.setText(undoEdit.getRedoPresentationName());
		} else {
			undoItem.setEnabled(false);
			redoItem.setEnabled(false);
			undoItem.setText("Undo");
			redoItem.setText("Redo");
		}
	} // end of updateMenu()

	public void undoableEditHappened(UndoableEditEvent ev) {
		StringBuffer buf = new StringBuffer(200);
		/*
		 * 当用户在Text Area中有所操作时，就可以用getEdit()方法取得UndoableEdit对象，此对象纪录着刚刚用户的操作，因
		 * 此可由些对象的undo()或redo()达到取消或复原的功能.
		 */
		undoEdit = ev.getEdit();
		buf.append("undoableEdit:");
		buf.append(undoEdit.getPresentationName());
		buf.append("\n");
		message.append(buf.toString());
		updateMenuItem();
	}// end of undoableEditHappened()

	public void changedUpdate(DocumentEvent e) {
		ShowDE(e);
	}

	public void insertUpdate(DocumentEvent e) {
		ShowDE(e);
	}

	public void removeUpdate(DocumentEvent e) {
		ShowDE(e);
	}

	public void ShowDE(DocumentEvent de) {
		StringBuffer debuf = new StringBuffer(100);
		debuf.append(de.getType());
		debuf.append(" Offset:");
		debuf.append(de.getOffset());
		debuf.append(" Length:");
		debuf.append(de.getLength());

		Element Eroot = jta.getDocument().getDefaultRootElement();
		DocumentEvent.ElementChange echange = de.getChange(Eroot);
		if (echange == null) {
			debuf.append("(No Element Change)");
		} else {
			debuf.append("Element Change:index ");
			debuf.append(echange.getIndex());
		}
		debuf.append("\n");
		message.append(debuf.toString());
	}

	public static void main(String[] args) {
		new TextArea_Element();
	}
}
